export enum ResultEnum {
    SUCCESS = 0,
    ERROR = -1,
    H5_NO_INVITE = -2,
    TOKEN_EXPIRE = 401,
    NO_PERMISSIONS = 403,
}

export enum ErrorMsg {
    NOT_FOUND = "未找到对应信息",
    ERROR = "操作失败",
}

export interface BaseResponseConfig {
    message?: string;
    code?: ResultEnum;
}

export interface IBaseResponse {
    code: number;
    message: string;
}

export class BaseResponse implements IBaseResponse {
    code: number;
    message: string;

    constructor(code: number = ResultEnum.SUCCESS, message: string = "success") {
        this.code = code ?? ResultEnum.SUCCESS;
        this.message = message ?? "success";
    }

    set({ message, code }: { message: string; code: number }): this {
        this.message = message;
        this.code = code;
        return this;
    }

    static success(message: string = "success"): BaseResponse {
        return new BaseResponse(ResultEnum.SUCCESS, message);
    }

    static error(message: string = ErrorMsg.ERROR, code: number = ResultEnum.ERROR): BaseResponse {
        return new BaseResponse(code, message);
    }
}

export interface IBaseResponseWithData<T = any> extends IBaseResponse {
    result: T;
}

export class BaseResponseWithData<T = any> extends BaseResponse implements IBaseResponseWithData<T> {
    result: T;

    constructor(result: T, config?: BaseResponseConfig | string) {
        if (typeof config === "string") {
            super(ResultEnum.SUCCESS, config);
        } else {
            super(config?.code ?? ResultEnum.SUCCESS, config?.message ?? "success");
        }
        this.result = result;
    }

    static override success<T>(result: T, message: string = "success"): BaseResponseWithData<T> {
        return new BaseResponseWithData(result, message);
    }

    static createError<T>(result: T, message: string = ErrorMsg.ERROR, code: number = ResultEnum.ERROR): BaseResponseWithData<T> {
        return new BaseResponseWithData(result, { message, code });
    }
}

export interface ErrorData<T> {
    result: T;
    code?: number;
    message?: string;
}

export interface IBaseResponseWithError<T = any> extends IBaseResponse {
    result: T;
}

export class BaseResponseWithError<T = any> extends BaseResponse implements IBaseResponseWithError<T> {
    result: T;

    constructor(error: ErrorData<T> | string, code?: number) {
        if (typeof error === "string") {
            super(code ?? ResultEnum.ERROR, error);
            this.result = {} as T;
        } else {
            const { result, code: errorCode, message } = error;
            super(errorCode ?? ResultEnum.ERROR, message ?? ErrorMsg.ERROR);
            this.result = result;
        }
    }

    static override error(message: string = ErrorMsg.ERROR, code: number = ResultEnum.ERROR): BaseResponseWithError<any> {
        return new BaseResponseWithError(message, code);
    }

    static createError<T>(error: ErrorData<T> | string, code?: number): BaseResponseWithError<T> {
        return new BaseResponseWithError(error, code);
    }
}
